package com.ease.plugin {
	import com.ease.core.plugin.ResourceBase;
	import com.ease.plugin.events.FactoryEvent;
	import com.ease.plugin.events.PluginManagerEvent;
	import com.ease.plugin.pluginClasses.PluginElement;
	import com.ease.plugin.pluginClasses.PluginManager;
	import com.ease.plugin.utils.PluginStrings;

	import flash.events.EventDispatcher;

	import mx.collections.ArrayCollection;

	[Event(name="pluginLoad", type="com.ease.plugin.events.FactoryEvent")]

	public class PluginFactory extends EventDispatcher {
		public function PluginFactory() {
			super();

			allItems = new ArrayCollection();
		}

		public function loadPlugin(resource:ResourceBase):void {
			createPluginManager();

			pluginManager.loadPlugin(resource);
		}

		public function addItem(item:PluginFactoryItem):void {
			if (item == null || item.id == null) {
				throw new ArgumentError(PluginStrings.getString(PluginStrings.INVALID_PARAM));
			}

			var items:ArrayCollection = allItems;

			// Make sure to overwrite any duplicate.
			var existingIndex:int = getIndexOfItem(item.id, items);
			if (existingIndex != -1) {
				items.setItemAt(item,existingIndex);
			}
			else {
				items.addItem(item);
			}
		}

		private static function getIndexOfItem(id:String, items:ArrayCollection):int {
			for (var i:int = 0; i < items.length; i++) {
				var item:PluginFactoryItem = items[i] as PluginFactoryItem;
				if (item.id == id) {
					return i;
				}
			}

			return -1;
		}

		public function createPluginElement(resource:ResourceBase):BaseElement {
			createPluginManager();

			var pluginElement:PluginElement = createPluginElementByResource(resource);

			if (pluginElement != null) {

				pluginElement.resource = resource;

				dispatchEvent
					( new FactoryEvent
						( FactoryEvent.PLUGIN_ELEMENT_CREATE
						, false
						, false
						, null
						, pluginElement
						)
					);
			}

			return pluginElement;
		}

		private function createPluginElementByResource( resource:ResourceBase, wrappedElement:BaseElement = null):PluginElement {
			var mediaElement:PluginElement = null;

			var items:ArrayCollection = getItemsByResource(resource, allItems);

			var item:PluginFactoryItem = items.getItemAt(0) as PluginFactoryItem;
			if (item != null) {
				mediaElement = invokeMediaElementCreationFunction(item);
			}
			return mediaElement;
		}

		private static function getItemsByResource(resource:ResourceBase, items:ArrayCollection):ArrayCollection {
			var results:ArrayCollection = new ArrayCollection();

			for each (var item:PluginFactoryItem in items) {
				if (item.canHandleResourceFunction(resource)) {
					results.addItem(item);
				}
			}

			return results;
		}

		private function invokeMediaElementCreationFunction(item:PluginFactoryItem):PluginElement {
			var mediaElement:PluginElement = null;
			try {
				mediaElement = item.pluginElementCreationFunction();
			}
			catch (error:Error) {
				// Swallow, the creation function is wrongly specified.
				// We'll just return a null MediaElement.
				trace(error.message);
			}
			return mediaElement;
		}

		private function createPluginManager():void {
			if (pluginManager == null) {
				pluginManager = new PluginManager(this);
				pluginManager.addEventListener(PluginManagerEvent.PLUGIN_LOAD, onPluginLoad);
//				pluginManager.addEventListener(PluginManagerEvent.PLUGIN_LOAD_ERROR, onPluginLoadError);
			}
		}

		private function onPluginLoad(event:PluginManagerEvent):void {
			dispatchEvent(new FactoryEvent(FactoryEvent.PLUGIN_LOAD, false, false, event.resource));
		}

		private var pluginManager:PluginManager;
		private var allItems:ArrayCollection;
	}
}